package com.glq1218.common.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类，用于连接Redis并执行相关操作。
 *
 * @author glq1218
 */
@Component
public class RedisUtils {
    /**
     * Spring Data Redis提供的RedisTemplate类，可以用于连接Redis并执行相关操作。
     */
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 构造函数，使用@Autowired注解将RedisTemplate对象注入到RedisUtil中。
     */
    @Autowired
    public RedisUtils(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 存储指定键值对到Redis中。
     *
     * @param key   键
     * @param value 值
     */
    public void put(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 存储指定键值对到Redis中，并设置过期时间。
     *
     * @param key      键
     * @param value    值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public void put(String key, Object value, long timeout, TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 从Redis中获取指定键的值。
     *
     * @param key 键
     * @return 键对应的值
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 从Redis中获取指定键的值。
     *
     * @param key   键
     * @param clazz 值的类型
     * @param <T>   泛型类型
     * @return 键对应的值
     */
    public <T> T get(String key, Class<T> clazz) {
        return clazz.cast(redisTemplate.opsForValue().get(key));
    }

    /**
     * 删除Redis中指定键的值。
     *
     * @param key 键
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true=设置成功；false=设置失败
     */
    public boolean setExpire(String key, long timeout, TimeUnit unit) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, unit));
    }

    /**
     * 判断指定键是否设置了过期时间。
     *
     * @param key 键
     * @return true如果指定键设置了过期时间，否则返回false
     */
    public boolean hasExpire(String key) {
        return Objects.equals(redisTemplate.getExpire(key), -1L);
    }

    /**
     * 获取指定键的剩余生存时间，单位为秒。
     *
     * @param key 键
     * @return 键的剩余生存时间（单位：秒），如果键不存在或者没有设置过期时间则返回-1
     */
    public long getExpire(String key) {
        Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
        return expire == null ? 0 : expire;
    }

    /**
     * 判断指定键是否已经过期。
     *
     * @param key 键
     * @return true如果指定键已经过期，否则返回false
     */
    public boolean isExpired(String key) {
        return Objects.equals(redisTemplate.getExpire(key), 0L);
    }
}
